package com.woniuxy.health.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Date 2023/9/11 0:51
 * @Author LZH
 * Description: OSS工具类
 */

@Data
@Slf4j
@Component
public class OSSUtil {

    //    @Value("${alibaba.bucket}")
//    private  String bucket;
//    @Value("${alibaba.cloud.access-key}")
//    private  String accessKey;
//    @Value("${alibaba.cloud.secret-key}")
//    private  String secretKey;
//    @Value("${alibaba.cloud.oss.endpoint}")
//    private String endpoint;
//
    private String bucket;
    private String accessKey;
    private String secretKey;
    private String endpoint;

    @Autowired
    public OSSUtil(@Value("${alibaba.bucket}") String bucket,
                   @Value("${alibaba.cloud.access-key}") String accessKey,
                   @Value("${alibaba.cloud.secret-key}") String secretKey,
                   @Value("${alibaba.cloud.oss.endpoint}") String endpoint) {
        this.bucket = bucket;
        this.accessKey = accessKey;
        this.secretKey = secretKey;
        this.endpoint = endpoint;
    }

    /**
     * 上传文件
     *
     * @param key      文件在OSS中的存储路径
     * @param filePath 本地文件路径
     */
    public void uploadFile(String key, String filePath) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            ossClient.putObject(bucket, key, new File(filePath));
            log.info("文件上传成功，Key: {}", key);
        } catch (Exception e) {
            log.error("文件上传失败，Key: {}", key, e);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 上传文件
     *
     * @param key         文件在OSS中的存储路径
     * @param inputStream 文件输入流
     */
    public void uploadFile(String key, InputStream inputStream) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            ossClient.putObject(bucket, key, inputStream);
            log.info("文件上传成功，Key: {}", key);
        } catch (Exception e) {
            log.error("文件上传失败，Key: {}", key, e);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 下载文件
     *
     * @param key       文件在OSS中的存储路径
     * @param localPath 本地保存路径
     */
    public void downloadFile(String key, String localPath) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            ossClient.getObject(new GetObjectRequest(bucket, key), new File(localPath));
            log.info("文件下载成功，Key: {}", key);
        } catch (Exception e) {
            log.error("文件下载失败，Key: {}", key, e);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 获取文件访问路径
     *
     * @param key 文件在OSS中的存储路径
     * @return 文件访问路径
     */
    public String getFileUrl(String key) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            LocalDateTime ldt = LocalDateTime.now().plusYears(10);
            Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
            return ossClient.generatePresignedUrl(bucket, key, date).toString();
        } catch (Exception e) {
            log.error("获取文件访问路径失败，Key: {}", key, e);
            return null;
        } finally {
            ossClient.shutdown();
        }
    }

    public String getKeyFromUrl(String url) {
        try {
            // 将URL字符串解析为URL对象
            URL parsedUrl = new URL(url);

            // 从URL路径中提取key值
            String path = parsedUrl.getPath();
            // 去除开头的斜杠
            String key = path.substring(1);

            return key;
        } catch (MalformedURLException e) {
            log.error("解析URL出错", e);
            return null;
        }
    }

    /**
     * 修改文件名为UUID
     *
     * @param originalFileName
     * @return
     */
    public String generateUUIDFileName(String originalFileName) {
        // 获取原始文件的后缀名
        String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));

        // 使用UUID生成新的文件名
        String uuidFileName = UUID.randomUUID().toString() + fileExtension;

        return uuidFileName;
    }

    /**
     * 删除文件
     *
     * @param key 文件在OSS中的存储路径
     */
    public void deleteFile(String key) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            ossClient.deleteObject(bucket, key);
            log.info("文件删除成功，Key: {}", key);
        } catch (Exception e) {
            log.error("文件删除失败，Key: {}", key, e);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 列举文件
     *
     * @param prefix 文件路径前缀，可为空
     * @return 文件列表
     */
    public List<OSSObjectSummary> listFiles(String prefix) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
        try {
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucket);
            listObjectsRequest.setPrefix(prefix);
            ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
            return objectListing.getObjectSummaries();
        } catch (Exception e) {
            log.error("列举文件失败，Prefix: {}", prefix, e);
            return null;
        } finally {
            ossClient.shutdown();
        }
    }
}
